home *** CD-ROM | disk | FTP | other *** search
- /*
- * USER.C
- * Network library interface routines
- * Generally called by the session layer
- *
- ****************************************************************************
- * *
- * part of: *
- * TCP/IP kernel for NCSA Telnet *
- * by Tim Krauskopf *
- * *
- * National Center for Supercomputing Applications *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- * *
- * Copyright (c) 1987, Board of Trustees of the University of Illinois *
- * *
- ****************************************************************************
- * Revisions:
- * 10/87 Initial source release, Tim Krauskopf
- * 2/88 typedef support for other compilers (TK)
- *
- */
- #define MASTERDEF 1
-
- #include <stdio.h>
- #include <string.h>
-
- #include <Events.h>
-
- #include "protocol.h"
- #include "data.h"
- #include "dlayer.h"
- #include "mactools.h"
- #include "protinit.h"
- #include "tcp.h"
- #include "tools.h"
- #include "userd.h" /* BYU 2.4.16 MPW */
- #include "ser.h" /* BYU 2.4.15 MPW */
-
- extern int /* BYU 2.4.16 */
- EtherNet; /* BYU 2.4.16 - Signify Drivers */
-
- extern int net_okay; /* BYU serial */
-
- extern short slip_connection; /* BYU 2.4.15 */
-
- #define LOWWATER 600
-
- #define UNKNOWN_PORT_TYPE 0 /* BYU 2.4.16 */
- #define MACTCP_PORT_TYPE 1 /* BYU 2.4.16 */
- #define NCSA_PORT_TYPE 2 /* BYU 2.4.16 */
-
- short porttype[NPORTS]; /* BYU 2.4.16 - 1 = MacTCP or 2 = NCSA */
-
- /***************************************************************************/
- int netporttype(int pnum) { /* BYU 2.4.16 */
- if (porttype[pnum] == NCSA_PORT_TYPE) /* BYU 2.4.16 */
- return(portlist[pnum]->type); /* BYU 2.4.16 */
- else /* BYU 2.4.16 */
- return(NOT_FROM_SLIP); /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
-
- /***************************************************************************/
- /* netread
- * Read from a connection buffer into a user buffer.
- * Returns number of bytes read, < 0 on error
- */
- int netread
- (
- int pnum,
- void *buffer,
- int n
- )
- int pnum,n;
- char *buffer;
- {
- int howmany,i;
- struct port *p;
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU 2.4.15 */
- return(-2);
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetread(pnum,buffer,n)); /* BYU 2.4.16 */
-
- if (NULL == (p = portlist[pnum]))
- return(-2);
-
- if (p->state != SEST) { /* foreign or netclose */
- if (p->state == SCWAIT) { /* ready for me to close my side? */
- if (!p->in.contain) {
- p->tcpout.t.flags = TFIN | TACK;
- tcpsend(p,0);
- p->state = SLAST;
- return(-1);
- }
- /* else, still data to be read */
- }
- else
- return(-1);
- }
-
- howmany = dequeue(&p->in,buffer,n); /* read from tcp buffer */
-
- i = p->in.size; /* how much before? */
-
- p->in.size += howmany; /* increment leftover room */
-
- if (i < LOWWATER && p->in.size >= LOWWATER) /* we passed mark */
- p->out.lasttime = 0L;
-
- if (p->in.contain) /* if still data to be read */
- netputuev(CONCLASS,CONDATA,pnum); /* don't forget it */
-
- return(howmany);
-
- } /* netread */
-
- /************************************************************************/
- /* netwrite
- * write something into the output queue, netsleep routine will come
- * around and send the data, etc.
- *
- */
- int netwrite
- (
- int pnum,
- void *buffer,
- int n
- )
- {
- int nsent,before;
- struct port *p;
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU 2.4.15 */
- return(-2);
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetwrite(pnum,buffer,n)); /* BYU 2.4.16 */
-
- p = portlist[pnum];
-
- if (p == NULL)
- return(-2);
-
- if ((p->type == 1) && (!slip_connection)) { /* BYU 2.4.15 */
- write_serial(buffer,n); /* BYU 2.4.15 */
- return(n); /* BYU 2.4.15 */
- } /* BYU 2.4.15 */
-
- if (p->state != SEST) /* must be established connection */
- return(-1);
-
- before = p->out.contain;
-
- nsent = enqueue(&p->out,buffer,n);
-
- if (!before) /* if this is something new, */
- p->out.lasttime = 0L; /* cause timeout to be true */
-
- return(nsent);
-
- } /* netwrite */
-
- /**************************************************************************/
- /* netpush
- * attempt to push the rest of the data from the queue
- * and then return whether the queue is empty or not (0 = empty)
- * returns the number of bytes in the queue.
- */
- int netpush
- (
- int pnum
- )
- {
- struct port *p;
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU 2.4.15 */
- return(-2);
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetpush(pnum)); /* BYU 2.4.16 */
-
- if (NULL == (p = portlist[pnum]))
- return(-2);
-
- p->out.push = 1;
-
- return(p->out.contain);
-
- } /* netpush */
-
- /**************************************************************************/
- /* netqlen
- * return the number of bytes waiting to be read from the incoming queue.
- */
- int /* BYU 2.4.16 MPW */
- netqlen(pnum)
- int pnum;
- {
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU serial */
- return(-2); /* BYU serial */
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetqlen(pnum)); /* BYU 2.4.16 */
-
- if (portlist[pnum] == NULL)
- return(-2);
-
- return(portlist[pnum]->in.contain);
-
- }
-
- /**************************************************************************/
- /* netroom()
- * return how much room is available in output buffer for a connection
- */
- int netroom
- (
- int pnum
- )
- {
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU serial */
- return(-2); /* BYU serial */
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetroom(pnum)); /* BYU 2.4.16 */
-
- if (portlist[pnum] == NULL || portlist[pnum]->state != SEST)
- return(-2);
-
- return(WINDOWSIZE - portlist[pnum]->out.contain);
-
- }
-
- /**************************************************************************/
- /* netsegsize and neterrchange and netsetip and netgetip
- *
- * set operating parameters to change them from the default values used.
- */
-
- netsegsize(newsize)
- int newsize;
- {
- int i;
-
- i = nnsegsize;
- nnsegsize = newsize;
-
- return(i);
- }
-
- netquench(newcredit)
- int newcredit;
- {
- int i;
-
- i = nncredit;
- nncredit = newcredit;
-
- return(i);
- }
-
- void netarptime /* dlayer timeout in secs */
- (
- int t
- )
- {
- nndto = t;
- }
-
- void netsetip
- (
- unsigned char *st
- )
- {
- /*
- * change all dependent locations relating to the IP number
- * don't worry about open connections, they must be closed by higher layer
- */
- movebytes(nnipnum,st,4);
-
- /* movebytes(arp.d.me,nnipnum,4); this is a bug - not needed */
-
- movebytes(arp.spa,nnipnum,4);
- movebytes(blankip.i.ipsource,nnipnum,4);
- movebytes(ulist.tcps.source,nnipnum,4);
- movebytes(ulist.udpout.i.ipsource,nnipnum,4);
-
- }
-
- void netgetip
- (
- unsigned char *st
- )
- {
- if (EtherNet == -99) /* BYU 2.4.16 */
- Mnetgetip(st); /* BYU 2.4.16 */
- else /* BYU 2.4.16 */
- movebytes(st,nnipnum,4); /* BYU 2.4.16 */
- }
-
- void netsetmask
- (
- unsigned char *st
- )
- {
- movebytes(nnmask,st,4);
- }
-
- void netgetmask
- (
- unsigned char *st
- )
- {
- movebytes(st,nnmask,4);
- }
-
- void netfromport /* next "open" will use this port */
- (
- int16 port
- )
- {
- nnfromport = port;
-
- }
-
- /**************************************************************************/
- /* netest?
- * is a particular session established yet?
- * Returns 0 if the connection is in the established state.
- */
- int netest
- (
- int pn
- )
- {
- struct port *p;
-
- if (pn < 0 || pn > NPORTS)
- return(-2);
-
- if (porttype[pn] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetest(pn)); /* BYU 2.4.16 */
-
- if (NULL == (p = portlist[pn]))
- return(-2);
-
- if (p->state == SEST)
- return(0);
-
- else if (p->state == SCWAIT) {
- if (!p->in.contain) {
- p->tcpout.t.flags = TFIN | TACK;
- tcpsend(p,0);
- p->state = SLAST;
- return(-1);
- }
- else
- return(0); /* still more data to be read */
- }
-
- return(-1);
-
- } /* netest */
-
- /**************************************************************************/
- /* netlisten
- * Listen to a TCP port number and make the connection automatically when
- * the SYN packet comes in. The TCP layer will notify the higher layers
- * with a CONOPEN event. Save the port number returned to refer to this
- * connection.
- *
- * usage: portnum = netlisten(service);
- * int service;
- *
- */
- int netlisten
- (
- uint serv, /* BYU 2.4.15 */
- short connectiontype /* BYU 2.4.15 */
- )
- {
- int pnum;
- struct port *prt;
- uint16 nn;
-
- if (!net_okay) /* BYU serial */
- return(-2); /* BYU serial */
-
- if (EtherNet == -99 && connectiontype == 0) { /* BYU 2.4.16 */
- pnum = Mnetlisten(serv); /* BYU 2.4.16 */
- if (pnum >= 0) /* BYU 2.4.16 */
- porttype[pnum] = MACTCP_PORT_TYPE; /* BYU 2.4.16 */
- return(pnum); /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
-
- pnum = makeport(connectiontype); /* BYU 2.4.15 */
-
- if (pnum < 0 || pnum >= NPORTS) /* BYU serial */
- return(-2);
-
- if (NULL == (prt = portlist[pnum]))
- return(-2);
-
- if (EtherNet == -99) { /* BYU 2.4.16 */
- porttype[pnum] = NCSA_PORT_TYPE; /* BYU 2.4.16 */
- prt->type = 1; /* BYU 2.4.16 */
- } else { /* BYU 2.4.16 */
- porttype[pnum] = UNKNOWN_PORT_TYPE; /* BYU 2.4.16 */
- prt->type = 0; /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
-
- prt->in.port = serv;
- prt->out.port = 0; /* accept any outside port #*/
- prt->in.lasttime = time(NULL); /* set time we started */
-
- prt->state = SLISTEN;
- prt->credit = 512; /* default value until changed */
- prt->tcpout.i.protocol = PROTTCP;
- prt->tcpout.t.source = intswap(serv); /* set service here too */
-
- /*
- * install maximum segment size which will be sent out in the first
- * ACK-SYN packet
- */
- prt->tcpout.x.options[0] = 2;
- prt->tcpout.x.options[1] = 4;
- /* install maximum segment size */
- nn = intswap(nnsegsize);
- movebytes(&prt->tcpout.x.options[2],&nn,2);
-
- return(pnum);
- } /* netlisten */
-
- /***********************************************************************/
- /* netgetftp
- * Provides the information that ftp needs to open a stream back to the
- * originator of the command connection. The other side's IP number
- * and the port numbers to be used to calculate the default data connection
- * number. Returns values in an integer array for convenient use in
- * PORT commands.
- */
- void netgetftp
- (
- int a[],
- int pnum
- )
- {
- struct port *p;
- uint i;
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) { /* BYU 2.4.16 */
- Mnetgetftp(a,pnum); /* BYU 2.4.16 */
- return; /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
-
- p = portlist[pnum];
-
- a[0] = p->tcpout.i.ipdest[0];
- a[1] = p->tcpout.i.ipdest[1];
- a[2] = p->tcpout.i.ipdest[2];
- a[3] = p->tcpout.i.ipdest[3];
- i = intswap(p->tcpout.t.source);
- a[4] = i >> 8;
- a[5] = i & 255;
- i = intswap(p->tcpout.t.dest);
- a[6] = i >> 8;
- a[7] = i & 255;
-
- } /* netgetftp */
-
- /**************************************************************************/
- /* netclose
- * Do appropriate actions to return connection state to SCLOSED which
- * enables the memory for that port to be reused.
- */
- int netclose
- (
- int pnum
- )
- {
- struct port *p;
-
- if (pnum < 0 || pnum > NPORTS) /* is a valid port? */
- return(-1);
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetclose(pnum)); /* BYU 2.4.16 */
-
- #if 1 /* BYU 2.4.15 */
- p = portlist[pnum]; /* BYU 2.4.15 */
- if ((p->type == 1) && (!slip_connection)) { /* BYU 2.4.15 */
- close_serial(); /* BYU 2.4.15 */
- return(0); /* BYU 2.4.15 */
- } else if ((p = portlist[pnum]) != NULL) { /* BYU 2.4.15 - something there */
- #else /* BYU 2.4.15 */
- if ((p = portlist[pnum]) != NULL) { /* something there */
- #endif /* BYU 2.4.15 */
- switch (p->state) {
- case SLISTEN: /* we don't care anymore */
- case SSYNS:
- p->state = SCLOSED;
- break;
- case SEST: /* must initiate close */
- /* send FIN */
- p->tcpout.t.flags = TACK | TFIN;
- tcpsend(p,0);
- p->state = SFW1; /* wait for ACK of FIN */
- break; /* do nothing for now ?*/
-
- case SCWAIT: /* other side already closed */
- p->tcpout.t.flags = TFIN | TACK;
- tcpsend(p,0);
- p->state = SLAST;
- break;
-
- case STWAIT: /* time out yet? */
- if (portlist[pnum]->out.lasttime + WAITTIME < time(NULL))
- p->state = SCLOSED;
- break;
-
- case SLAST: /* five minute time out */
- if (portlist[pnum]->out.lasttime + LASTTIME < time(NULL))
- p->state = SCLOSED;
- break;
- default:
- break;
- }
- }
- else
- return(1);
- return(0);
- } /* netclose */
-
- /**********************************************************************/
-
- int doconnect
- (
- int pnum,
- int service,
- int mseg
- )
- {
- uint16 seg;
- struct port *p;
-
- p = portlist[pnum];
-
- p->tcpout.i.protocol = PROTTCP; /* this will be TCP socket */
- p->tcpout.t.dest = intswap(service); /* for example, telnet=23 */
- p->out.port = service; /* service is same as port num*/
- p->tcpout.t.flags = TSYN; /* want to start up sequence */
- p->tcpout.t.ack = 0; /* beginning has no ACK */
-
- p->state = SSYNS; /* syn sent */
- /*
- * install maximum segment size which will be sent out in the first
- * ACK-SYN packet
- */
- p->tcpout.x.options[0] = 2;
- p->tcpout.x.options[1] = 4;
- /* install maximum segment size */
- seg = intswap(mseg);
- movebytes(&p->tcpout.x.options[2],&seg,2);
-
- p->tcpout.t.hlen=96; /* include one more word in hdr */
- tcpsend(p,4); /* send opening volley */
- p->tcpout.t.hlen=80; /* normal hdr len */
-
- /* savenxt = p->out.nxt; */
- p->out.nxt += 1; /* ack should be for next byte */
-
- return(pnum); /* do not wait for connect */
- } /* doconnect */
-
- /**************************************************************************/
- /* netxopen
- * Open a network socket for the user.
- *
- */
- int netxopen
- (
- uint8 *machine,
- uint service,
- uint rto,
- uint mtu,
- uint mseg,
- uint mwin, /* BYU 2.4.15 */
- short connectionType /* BYU 2.4.15 */
- )
- {
- struct port *p;
- int pnum,ret,i;
- uint8 *pc,*hiset;
-
- if (EtherNet == -99 && connectionType == 0) { /* BYU 2.4.16 */
- pnum = Mnetxopen((uint32 *) machine,service,rto,mtu,mseg,mwin); /* BYU 2.4.16 */
- if (pnum >= 0) /* BYU 2.4.16 */
- porttype[pnum] = MACTCP_PORT_TYPE; /* BYU 2.4.16 */
- return(pnum); /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
-
- /*
- * check the IP number and don't allow broadcast addresses.
- *
- * If the AND of the original and the mask does not change the value then
- * the host portion is all zeros.
- * If the OR of the original and the inverse mask does not change the value
- * then the host portion is all ones.
- */
- ret = 0; /* assume all are the same */
- for (i=0; i<4; i++)
- if (machine[i] != (machine[i] & nnmask[i]))
- ret = 1;
-
- if (!ret) { /* if all are the same, reject broadcast addr */
- nnerror(506);
- return(-4);
- }
-
- ret = 0;
- for (i=0; i<4; i++)
- if (machine[i] != (uint8)(machine[i] | (~nnmask[i])))
- ret = 1;
-
- if (!ret) { /* if all are the same, reject broadcast addr */
- nnerror(506);
- return(-4);
- }
-
- netsleep(0); /* make sure no waiting packets */
- pnum = makeport(connectionType);/* BYU 2.4.15 */
-
- if (pnum < 0)
- return(-3);
-
- porttype[pnum] = NCSA_PORT_TYPE; /* BYU 2.4.16 */
-
- p = portlist[pnum]; /* create a new port */
- /*
- * make a copy of the ip number that we are trying for
- */
- movebytes(p->tcpout.i.ipdest,machine,4);
- movebytes(p->tcps.dest,machine,4); /* pseudo header needs it */
-
- /*
- * get the hardware address for that host, or use the one for the gateway
- * all handled by 'netdlayer' by ARPs.
- */
- if (!connectionType) { /* BYU 2.4.15 */
- pc = netdlayer(machine); /* we have ether? */
-
- if (pc == NULL) { /* cannot connect to local machine */
- nnerror(504);
- return(-2);
- }
-
- movebytes(p->tcpout.d.dest,pc,DADDLEN); /* load it up */
- } /* BYU 2.4.15 */
-
- /*
- * Add in machine specific settings for performance tuning
- */
- if (rto > MINRTO)
- p->rto = rto; /* starting retrans timeout */
- if (mtu < TMAXSIZE) /* largest packet space we have */
- p->sendsize = mtu; /* maximum transmit size for that computer */
- if (mwin < WINDOWSIZE) /* buffer size is the limit */
- p->credit = mwin; /* most data that we can receive at once */
-
- /* Connection type: 0 is non-serial, 1 is serial or SLIP */ /* BYU 2.4.15 */
- p->mseg = mseg; /* BYU 2.4.15 */
- p->service = service; /* BYU 2.4.15 */
- p->type = connectionType; /* BYU 2.4.15 */
- if ((connectionType == 1) && !slip_connection) { /* BYU 2.4.15 */
- p->state = SEST; /* BYU 2.4.15 */
- pnum = open_serial(pnum); /* BYU 2.4.15 */
- return(pnum); /* BYU 2.4.15 */
- } /* BYU 2.4.15 */
-
- #ifdef MAC
- if (nnemac) {
- #endif
- /*
- * quick check to see if someone else is using your IP number
- * Some boards receive their own broadcasts and cannot use this check.
- * The Mac will only use this check if it is using EtherTalk.
- */
- i = cachelook(nnipnum,0,0); /* don't bother to ARP */
- if (i >= 0) { /* if it is not -1, we are in trouble */
- hiset = (uint8 *)arpc[i].hrd;
- pc = neterrstring(-1);
- sprintf(pc,"Conflict with Ethernet hardware address: %2x:%2x:%2x:%2x:%2x:%2x",
- hiset[0],hiset[1],hiset[2],hiset[3],hiset[4],hiset[5]);
- nnerror(-1);
- nnerror(102);
- netclose(pnum);
- return(-3);
- }
- #ifdef MAC
- }
- #endif
-
- /*
- * make the connection, if you can, we will get an event notification later
- * if it connects. Timeouts must be done at a higher layer.
- */
- ret = doconnect(pnum,service,mseg);
-
- return(ret);
- } /* netxopen */
-
- #if 0 /* BYU 2.4.15 - not used */
- /**************************************************************************/
- /* netopen
- * Netopen is a cheap way to open a connection without looking up any
- * machine information. Uses suitable default values for everything.
- */
- netopen(s,tport)
- unsigned char *s;
- uint tport;
- {
-
- return(netxopen(s,tport,MINRTO,TSENDSIZE,DEFSEG,DEFWINDOW));
- }
- #endif /* BYU 2.4.15 */
-
- /*************************************************************************/
- /* netopen2
- * Send out repeat SYN on a connection which is not open yet
- * Checks, and only sends one if needed.
- * Returns 1 if the state is still SYNS and 0 if the connection has proceeded.
- * The timing is all handled at a higher layer.
- */
- int netopen2
- (
- int pnum
- )
- {
- struct port *p;
-
- if (pnum < 0 || pnum > NPORTS)
- return(-1);
-
- if (porttype[pnum] == MACTCP_PORT_TYPE) /* BYU 2.4.16 */
- return(Mnetopen2(pnum)); /* BYU 2.4.16 */
-
- if (NULL == (p = portlist[pnum]))
- return(-2);
-
- if (p->state != SSYNS)
- return(0); /* done our job */
- /*
- * The connection has not proceeded to further states, try retransmission
- */
-
- p->out.nxt--;
- p->tcpout.t.hlen=96; /* include one more word in hdr */
- tcpsend(p,4); /* try sending again */
- p->tcpout.t.hlen=80; /* normal hdr len */
- p->out.nxt++;
-
- return(1);
- } /* netopen2 */
-
- /**************************************************************************/
- /* netinit
- * Calls all of the various initialization routines that set up queueing
- * variables, static values, reads configuration files, etc.
- */
-
- int netinit
- (
- void
- )
- {
- int ret;
-
- if (EtherNet == -99) /* BYU 2.4.16 */
- Mnetinit(); /* BYU 2.4.16 - initialization for MacTCP */
-
- /*
- * Initializes all buffers and hardware for data link layer.
- * Machine/board dependent.
- */
- ret = dlayerinit();
-
- if (ret) {
- nnerror(101);
- return(ret);
- }
- /*
- * initialize the template packets needed for transmission
- */
- ret = protinit();
-
- return(ret); /* set up empty packets */
- } /* netinit */
-
- /*************************************************************************/
- /* netshut
- * Close all the connections and turn off the hardware.
- */
- void netshut
- (
- void
- )
- {
- int i;
-
- if (EtherNet == -99) /* BYU 2.4.16 */
- Mnetshut(); /* BYU 2.4.16 - for MacTCP */
-
- for (i=0; i < NPORTS ; i++)
- if (portlist[i] != NULL)
- netclose(i);
-
- netsleep(1);
-
- dlayershut();
- }
-
- /*************************************************************************/
- /* neteventinit
- * load up the pointers for the event queue
- * makes a circular list to follow, required for error messages
- */
- void neteventinit
- (
- void
- )
- {
- int i;
-
- for (i=0; i < NEVENTS; i++)
- nnq[i].next = i+1;
-
- nnq[NEVENTS-1].next = -1;
-
- nnefirst = 0;
- nnelast = 0;
- nnefree = 1;
- } /* neteventinit */
-